;File match_checker.lisp
;Abstract:
;	-Handles the actual swapping of elements
;	-Checks entire board for matches
;	-if there are matches, set matching elements to -1; otherwise, swap back
;	-create function Check-For-Matches(level r1 c1 r2 c2)
;;*****************************************************************************
;; asumes valid inputs...?
;; should be in a separate file?
;; pay attention to which way rows and cols are numbered... match rest of program...?
;; will switching them make a difference?
;; reset hasChanged to false
;; if not return original, else return new level.
;; swape forward from a to b (lower number start from -1)
;;*****************************************************************************
;(defun Check-For-Matches (level row1 col1 row2 col2) ;;Ignore this code
;(if (= col1 col2)
;
;(x (nth col1 level  )  )
;(rotatef (nth (incf n) x)
;(nth (incf n) x) ) x)  )  )
;)
(load "match_handler.lisp")
(load "game.lisp")

;;*****************************************************************************
;; GOOD VERSION!!!(MatchChecker)
;; called by checkback
(defun threematch (x) (cond ( (null (cdr (cdr x) ) ) '(nil nil) ) (t (append (list(= (car x) (cadr x) (caddr x) ) ) (threematch (cdr x)  ) ) ) ) ) ;; ?set hasChanged to true here?(match-checker)
;;*****************************************************************************
;; GOOD VERSION!!!(MatchChecker)
;; called by checkmatch
(defun checkback (x)  
  (let  (  (tm (threematch x)  )  )
    (if (>= (length tm) 3)
      (cons
        (if (or (car tm) (cadr tm) (caddr tm)  )
          -1 (caddr x)
        )
        (checkback (cdr x)  )
      )
    )
  )
)
;;*****************************************************************************
;; GOOD VERSION!!!(MatchChecker)
(defun checkmatch (x) 
  (let  (  (tm (threematch x)  )  )
    (append
      (list
        ( if (equal t (car tm)) -1 (car x))
        ( if (OR (car tm) (cadr tm) ) -1 (cadr x))
      )
      (checkback x)
    )
  )
)
;;*****************************************************************************
;; Works!
;; http://stackoverflow.com/questions/3513128/swapping-rows-and-columns-in-common-lisp
(defun rotate (list-of-lists)
  (apply #'mapcar #'list list-of-lists))
;;*****************************************************************************
;; returns if either one is -1 return -1 else return x (could have been y, y and x should be equal to each other at this spot)
(defun n1rules (x y) (if (OR ( = -1 x ) ( = -1 y) ) -1 x ))
;;*****************************************************************************
;; applies the n1rules test to two lists
(defun n1ruleslist (x y) (mapcar #'n1rules x y))
;;*****************************************************************************
;; returns the list of lists that is the game board
;;  with the values that are matches as -1
;; lst is the table
(defun match-checker (lst)
  (let (  ( vmatch (mapcar #'checkmatch lst)  )  
    ( hmatch (rotate (mapcar #'checkmatch (rotate lst)  )  )  )
    )
    (mapcar #'n1ruleslist vmatch hmatch)
  )
)
;;*****************************************************************************
;; takes the list with the swapped positions
(defun isChanged (lst) (equal lst (match-checker lst)))
;;*****************************************************************************
;; just playing with code below...

;; Rotatef funtion for swapping (Do not use this for swapping)
;(let ((n 3);;swape backward from b to a(higher number start from 2)
;                       (x (list 'a 'b 'c 'd 'e 'f 'g)))
;                   (rotatef (nth (decf n) x)
;                            (nth (decf n) x) ) x)
;;(A C B D E F G)

;(let ((n -1);; swape forward from a to b (lower number start from -1) ;;Do not use this for swapping
;                       (x (list 'a 'b 'c 'd 'e 'f 'g)  )  )
;                   (rotatef (nth (incf n) x)
;                            (nth (incf n) x) ) x)
;;(B A C D E F G)

;; this only does a swap when it's the same column, in progress...
;(defun colCheck (level row1 row2 col) ;;This code is for swapping, if need to use this code don't forget to confirm with Bryan to make sure it working fine.
;(let (  (n (if (< row1 row2 ) row1 row2 )  )
;(x (nth col level)  )  )
;(rotatef 
;(nth (decf n) x)
;(nth (decf n) x) ) x)  )
;; close? has errors...
;(colcheck '((1 2 3 4) (5 6 7 8) (9 10 11 12) (13 14 15 16)) 1 2 4)
;;NTH: -1 is not a non-negative integer
;;*****************************************************************************
;______MICHAELS SWAP FUNCTION: WORKS_______________
;(defun elemSwap (level r1 c1 r2 c2)
;  (let ((e1) (e2) (n))
;    (progn (setf n (list-length (nth 0 level)) e1 (nth (- r1 1) (nth (- c1 1) level)) e2 (nth (- r2 1) (nth (- c2 1) level))) ;sets variables
;      (setf (nth (- r1 1) (nth (- c1 1) level)) e2 (nth (- r2 1) (nth (- c2 1) level)) e1) ;set e1 to e2, and then e2 to e1
;      level ;returns new level
;    )
;  )
;)

;______MICHAELS SWAP FUNCTION: WORKS_______________
(defun elemSwap (level r1 c1 r2 c2)
  (let ((e1) (e2) (n))
    (progn (setf n (list-length (nth 0 level)) e1 (nth (- r1 1) (nth (- c1 1) level)) e2 (nth (- r2 1) (nth (- c2 1) level))) ;sets variables
      (setf (nth (- r1 1) (nth (- c1 1) level)) e2 (nth (- r2 1) (nth (- c2 1) level)) e1) ;set e1 to e2, and then e2 to e1
      level ;returns new level
    )
  )
)


;(defun elemSwap (level r1 c1 r2 c2)
;  (let ((e1) (e2) (n))
;    (progn (setf n (list-length (nth 0 level)) e1 (nth (- n r1) (nth (- c1 1) level)) e2 (nth (- n r2) (nth (- c2 1) level))) ;sets variables
;      (setf (nth (- n r1) (nth (- c1 1) level)) e2 (nth (- n r2) (nth (- c2 1) level)) e1) ;set e1 to e2, and then e2 to e1
;      level ;returns new level
;    )
;  )
;)


;;*****************************************************************************
;; how did we deside to number these? '((4 3 2 1) (8 7 6 5) (12 11 10 9) (16 15 14 13))? 1 being bottom left? bl to tl, then l to r?
;;*****************************************************************************
;(elemswap '((1 2 3 4) (5 6 7 8) (9 10 11 12) (13 14 15 16)) 2 3 3 3)
;;((1 2 3 4) (5 6 7 8) (9 11 10 12) (13 14 15 16))
;; 10 and 11 changed places

;(elemswap '((1 2 3 4) (5 6 7 8) (9 10 11 12) (13 14 15 16)) 3 4 4 4)
;;((1 2 3 4) (5 6 7 8) (9 10 11 12) (14 13 15 16))
;;14 and 13 changed places

;(elemswap '((1 2 3 4) (5 6 7 8) (9 10 11 12) (13 14 15 16)) 4 4 3 4)
;;((1 2 3 4) (5 6 7 8) (9 10 11 12) (14 13 15 16))
;;14 and 13 changed places

;(elemswap '((1 2 3 4) (5 6 7 8) (9 10 11 12) (13 14 15 16)) 1 1 1 2)
;;((1 2 3 8) (5 6 7 4) (9 10 11 12) (13 14 15 16))
;;4 and 8 changed places

;(elemswap '((4 3 2 1) (8 7 6 5) (12 11 10 9) (16 15 14 13)) 2 1 1 1)
;;((4 3 1 2) (8 7 6 5) (12 11 10 9) (16 15 14 13))
;;swaps 2 and 1

;;*****************************************************************************
;; I think Check-For-Matches should be renamed, and spit up?, but others maybe using it...?

;(defun Check-For-Matches (level row1 col1 row2 col2)
; (let* ((swappedLevel (elemSwap level row1 col1 row2 col2))
;		(newLevel (match-checker swappedLevel)))
;  (if (equal newLevel swappedLevel)
;    level
;	(progn (swap-r) (handle-matches newLevel)) ;this returns in form -1s. So run it through match-handler later?
;       ;newLevel
;  )
; )
;)

(defun Check-For-Matches (level row1 col1 row2 col2) ;;testing tesitng ttesinging
  (if (equal (match-checker (elemSwap level row1 col1 row2 col2)) (elemSwap level row1 col1 row2 col2)) level
    ;; this line is a hack (1 1 1 1) part at least, using existing code not like intended
    (Check-For-Matches (handle-matches (Match-checker (elemSwap level row1 col1 row2 col2))) 1 1 1 1)
  )
)
;;This also checks for recursion, after the '1's go away the '5's should be lined up, and then go away
;(check-for-matches '((1 2 3 4) (1 5 7 8) (1 5 11 12) (5 14 15 16)) 1 1 1 2)
;;((2 3 4 3) (7 8 2 3) (11 12 1 4) (14 15 16 0))

;;*****************************************************************************
